package com.jd.ymcc.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.jd.ymcc.domain.*;
import com.jd.ymcc.dto.RedisRegisterDto;
import com.jd.ymcc.feigin.LoginFeignClient;
import com.jd.ymcc.dto.RegisterDto;
import com.jd.ymcc.enums.GlobalErrorCode;
import com.jd.ymcc.mapper.UserMapper;
import com.jd.ymcc.result.JSONResult;
import com.jd.ymcc.service.*;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.jd.ymcc.until.AssertUtil;
import com.jd.ymcc.until.BitStatesUtils;
import com.jd.ymcc.until.CommonConstants;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.LongValue;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author director
 * @since 2022-09-23
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;
    @Autowired
    private LoginFeignClient loginFeignClient;
    @Autowired
    private IUserBaseInfoService userBaseInfoService;
    @Autowired
    private IUserAccountService userAccountService;
    @Autowired
    private IUserCodeService userCodeService;
    @Autowired
    private IUserIntegralLogService userIntegralLogService;
    @Autowired
    private UserMapper userMapper;

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void smsRegister(RegisterDto smsRegisterDto) {
        // 1.参数校验，使用JSR303已完成校验
        // 2.验证码在Redis中是否过期/存在
        String key = String.format(CommonConstants.Register_PHONE_PREFIX, smsRegisterDto.getMobile());
        Object o = redisTemplate.opsForValue().get(key);
        // 2.1.校验验证码是否存在，如果不存在那么说明已过期，或者用户非法访问
        AssertUtil.isNotNull(o, GlobalErrorCode.USER_EXIST_ERROR);
        // 3.校验验证码是否正确
        RedisRegisterDto registerDto = (RedisRegisterDto) o;
        AssertUtil.isEquals(registerDto.getCode(), smsRegisterDto.getSmsCode(), GlobalErrorCode.CODE_MISMATCH_ERROR);
        // 3.手机号是否被注册过了，如果已经存在那么抛出异常
        // 3.1.根据电话号码查询用户信息
        User user = selectByPhone(smsRegisterDto.getMobile());
        AssertUtil.isNull(user, GlobalErrorCode.USER_EXIST_ERROR);
        // 4.保存t_login，使用uaaFeign
        JSONResult jsonResult = saveLogin(smsRegisterDto);
        System.out.println(jsonResult);
        // 4.1.判断服务方是否熔断，如果熔断那么就是服务不可用
        AssertUtil.isTrue(jsonResult.isSuccess(), GlobalErrorCode.ERROR);
        // 4.2.判断是否保存成功，如果成功那么data中有loginId
        AssertUtil.isNotNull(jsonResult.getData(), GlobalErrorCode.NULL);
        Long loginId = Long.valueOf(jsonResult.getData().toString());
        // 5.保存t_user、t_user_account、t_user_base_info
        User saveUser = saveUser(loginId, smsRegisterDto);
        AssertUtil.isNotNull(saveUser.getId(), GlobalErrorCode.NULL);
        initUserAccount(saveUser.getId());
        initUserBaseInfo(saveUser.getId(), smsRegisterDto);
        //通过过注册码，获取积分10
        String recode = smsRegisterDto.getRecode();
        //1.判断推荐码是否正确
        UserCode userCode = userCodeService.selectById(1L);
        String code = userCode.getCode();
        if (recode.equals(code)){
            User user1 = selectById(1L);
            int i = user1.getIntegral();
            System.out.println(i);
            i=i+10;
            user1.setIntegral(i);
            userMapper.insert(user1);
            UserIntegralLog userIntegralLog = new UserIntegralLog();
            userIntegralLog.setCreateTime(new Date());
            userIntegralLog.setUserId(3L);
            userIntegralLog.setScore(user1.getIntegral());

            userIntegralLogService.insert(userIntegralLog);
            UserGrowLog userGrowLog = new UserGrowLog();
            BeanUtils.copyProperties(userIntegralLog,userGrowLog);
            log.info("积分成长值送达");

        }
        log.info("推荐码没有哦，不能送积分");

    }

    /*
     * @Description: 初始化用户基本信息
     * @Author: Director
     * @Date: 2022/8/17 21:38
     * @param id: user主键Id
     * @return: void
     **/
    private void initUserBaseInfo(Long userId, RegisterDto smsRegisterDto) {
        UserBaseInfo userBaseInfo = new UserBaseInfo();
        userBaseInfo.setId(userId);
        userBaseInfo.setCreateTime(new Date().getTime());
        userBaseInfo.setRegChannel(smsRegisterDto.getRegChannel());
        userBaseInfoService.insert(userBaseInfo);
    }

    /*
     * @Description: 初始化用户账户信息
     * @Author: Director
     * @Date: 2022/8/17 21:37
     * @param userId: user主键Id
     * @return: void
     **/
    private void initUserAccount(Long userId) {
        UserAccount userAccount = new UserAccount();
        userAccount.setId(userId);
        userAccount.setCreateTime(new Date().getTime());
        // 此处成功发送邮件告知用户初始支付密码
        userAccount.setPassword("123456");
        userAccountService.insert(userAccount);
    }

    /*
     * @Description: 保存用户信息
     * @Author: Director
     * @Date: 2022/8/17 21:32
     * @param loginId: 用户loginId
     * @param smsRegisterDto: 用户注册对象
     * @return: cn.itsource.domain.User
     **/
    private User saveUser(Long loginId, RegisterDto smsRegisterDto) {
        User user = new User();
        user.setLoginId(loginId);
        user.setCreateTime(new Date().getTime());
        user.setPhone(smsRegisterDto.getMobile());
        user.setNickName(smsRegisterDto.getMobile());
        //添加状态值
        long bitState = BitStatesUtils.addState(BitStatesUtils.OP_REGISTED, BitStatesUtils.OP_ACTIVED);
        bitState = BitStatesUtils.addState(bitState, BitStatesUtils.OP_AUTHED_PHONE);
        // 设置用户初始为状态值
        user.setBitState(bitState);
        insert(user);
        return user;
    }

    /*
     * @Description: 保存login
     * @Author: Director
     * @Date: 2022/8/17 21:17
     * @param smsRegisterDto: 用户注册信息
     * @return: cn.itsource.result.JsonResult
     **/
    private JSONResult saveLogin(RegisterDto smsRegisterDto) {
        Login login = new Login();
        login.setUsername(smsRegisterDto.getMobile());
        login.setPassword(smsRegisterDto.getPassword());
        login.setType(Login.USER_TYPE);
        login.setEnabled(Login.ENABLE);
        return loginFeignClient.saveOrUpdate(login);
    }

    /*
     * @Description: 根据电话查询用户
     * @Author: Director
     * @Date: 2022/8/17 21:12
     * @param mobile: 用户电话
     * @return: cn.itsource.domain.User
     **/
    private User selectByPhone(String mobile) {
        // 1.创建Wrapper包装器
        Wrapper<User> wrapper = new EntityWrapper<>();
        // 2.传入sql条件
        wrapper.eq("phone", mobile);
        return selectOne(wrapper);
    }



}
